﻿/*
 * ringbuf_v.hpp
 *
 *  Created on: 2016年12月16日
 *      Author: work
 */

#ifndef INCLUDE_DM_RINGBUF_V_HPP_
#define INCLUDE_DM_RINGBUF_V_HPP_

#include <dm/ringpos_v.hpp>
#include <dm/ringpos.hpp>

namespace dm{

template<typename TValue,typename TSize,TSize Size,typename TPos=TSize>
class CRingBufV{
	CRingBufV(const CRingBufV&);
	CRingBufV& operator=( const CRingBufV& );
public:
	typedef CRingPosV<TPos,TSize,Size> pos_v_t;
	typedef CRingPos<TPos,TSize,Size> pos_t;

public:
	CRingBufV():m_p(){}

	static inline const TSize getSize(){
		return Size;
	}

	inline pos_t getPos()const{
		pos_t p = m_p;
		return p;
	}

	inline void getPos( pos_t& p )const{
		p = m_p;
	}

	inline const TValue& getData( const pos_t& p )const{
		return m_d[p.getPos()];
	}

	inline void getData( TValue& v,const pos_t& p )const{
		v = m_d[p.getPos()];
	}

	inline TSize getData( TValue* buf,TSize size,pos_t p )const{
		return getDataAndMovePos(buf,size,p);
	}

	TSize getDataAndMovePos( TValue* buf,TSize size,pos_t& p )const;

	inline void push( const TValue& v ){
		m_d[m_p.getPos()] = v;
		++m_p;
	}

	void push( const TValue* v,TSize len );

private:
	TValue m_d[Size];
	pos_v_t m_p;
};

template<typename TValue,typename TSize,TSize Size,typename TPos>
TSize CRingBufV<TValue,TSize,Size,TPos>::getDataAndMovePos( TValue* buf,TSize size,CRingBufV<TValue,TSize,Size,TPos>::pos_t& p )const{
	TSize c = 0;
	for(;c<size && p!=m_p;++c,++buf )
		*buf = m_d[p.getPos()];

	return c;
}

template<typename TValue,typename TSize,TSize Size,typename TPos>
void CRingBufV<TValue,TSize,Size,TPos>::push( const TValue* buf,TSize len ){
	for(;len>0;++buf,--len )
		push( *buf );
}

}

#endif /* INCLUDE_DM_RINGBUF_V_HPP_ */
